<?php

/**
 * 安心站长axzz.cn，一个追求技术创造者。让网站、小程序、APP牛起来……
 *
 * cighsen02 365182575
 *
 * Create at: 2024.04.23
 * Update at: 2025.11.24
 */

namespace Twoir\Service;

use Exception;
use Twoir\System\Model\EnewsMember;
use Twoir\System\Support\ParamTrait;

/**
 * 会员基本功能
 */
class BaseMember
{
    use ParamTrait;
    // 当前登陆用户
    protected $user;
    // 允许字段 用户提交过滤
    const ALLOW = ['classid', 'id', 'cid', 'cname', 'add', 'del', 'edit'];
    // 简洁方式
    const SIMPLE_FIELD 	= ['userid','username','email','groupid','ingid','agid','userfen','phno','upic'];
    // 完整方式
    const FULL_FIELD 	= [
        'userid',
        'username',
        'email',
        'groupid',
        'userfen',
        'money',
        'userdate',
        'zgroupid',
        'havemsg',
        'registertime',
        'ingid',
        'agid',
        'isern',
        'isot',
        'phno',
        'upic',
        'mustdo',
        'rndt',
        'userjyz',
        'usertitle'
    ];
    // 时间
    protected int $nowtime;

    protected string $ip;

    protected int $port;
    /**
     * 是否强制验证登陆
     *
     * @param bool $verifyLogin
     */
    public function __construct(bool $verifyLogin = true)
    {
        $this->nowtime  = time();
        $this->ip       = egetip();
        $this->port     = egetipport();

        $verifyLogin ? $this->isLogin() : $this->userInfo();
    }

    /**
     * 是否登陆
     *
     * @param bool $isSimple 是否返回简洁信息 默认返回简单
     * @return array
     *
     * @throws Exception
     */
    protected function isLogin(bool $isSimple = true): array
    {
        $userid 	= (int)getcvar('mluserid');
        $username 	= getcvar('mlusername');
        $username	= RepPostVar($username);
        $rnd 		= getcvar('mlrnd');
        $rnd 		= RepPostVar($rnd);

        if(!$userid || !$username || !$rnd)	{

            $this->user = null;
            throw new Exception('您还没登录!', 2200);
        }

        $qcklgr = $this->qCheckLoginAuthstr();
        if(!isset($qcklgr['islogin']) || !$qcklgr['islogin']) {

            $this->user = null;
            EmptyEcmsCookie();

            throw new Exception('同一帐号同一时刻只能一人在线!', 2200);
        }

        $field = $isSimple ? [...static::SIMPLE_FIELD, 'userdate', 'zgroupid', 'checked'] : [...static::FULL_FIELD, 'checked'];

        $cr = EnewsMember::getOne(['userid' => $userid, 'username' => $username, 'rnd' => $rnd], $field);

        if(!isset($cr['userid']) || empty($cr['userid'])){

            $this->user = null;
            EmptyEcmsCookie();

            throw new Exception('同一帐号同一时刻只能一人在线!', 2200);
        }

        if(0 == $cr['checked']){

            $this->user = null;
            EmptyEcmsCookie();

            throw new Exception('您的帐号还未通过审核', 2200);
        }

        // 默认会员组
        if(empty($cr['groupid'])){

            $cr['groupid'] = eReturnMemberDefGroupid();

            EnewsMember::update(['userid' => $cr['userid']], ['groupid' => $cr['groupid']]);
        }

        // 是否过期
        if($cr['userdate'] && ($cr['userdate'] - time() <= 0))	{

            $update 		= ['userdate' => 0];
            $cr['userdate'] = 0;
            if($cr['zgroupid'])	{

                $update 		+= ['groupid' => $cr['zgroupid']];
                $cr['zgroupid'] = 0;
            }

            EnewsMember::update(['userid' => $cr['userid']], $update);
        }

        // 赋值
        $this->user = $cr;

        return $this->filter($cr, $isSimple) + $this->getLevel($cr['groupid']);
    }

    /**
     * 退出登陆
     *
     * @return void
     */
    public function logout()
    {
        global $ecms_config;

        if (!empty($user = $this->userInfo())) {

            $update = [$this->egetmf('isot') => 0];
            // 更新rnd
            if(isset($ecms_config['sets']['mpchmrnd']) && 0 === $ecms_config['sets']['mpchmrnd']) {
                $update += [
                    $this->egetmf('rnd')    => make_password(EcmsRandInt(20,36)),
                    $this->egetmf('rndt')   => make_password(EcmsRandInt(20,32))
                ];
            }

            EnewsMember::update(['userid' => $user['userid']], $update);
        }

        EmptyEcmsCookie();
    }

    /**
     * 获取字段名
     *
     * @param string $field
     * @return string
     */
    protected function egetmf(string $field): string
    {
        global $ecms_config;
        // 原版
        if(isset($ecms_config['member']['chmember']) && 0 === $ecms_config['member']['chmember'])
        {
            return $field;
        }

        return $ecms_config['memberf'][$field] ?? $field;
    }

    /**
     * 返回登陆用户信息
     *
     * @return array
     */
    public function getLoginInfo(): array
    {
        return $this->userInfo();
    }

    /**
     * 返回已经登陆用户信息
     *
     * @return array
     */
    protected function userInfo(): array
    {
        try {

            $result = $this->user ? $this->filter($this->user, true) + $this->getLevel($this->user['groupid']) : $this->isLogin();
        }
        catch (Exception $e) {

            return [];
        }

        return $result;
    }

    /**
     * 返回默认会员组ID
     *
     * @return int
     */
    public function returnMemberDefGroupid(): int
    {
        global $ecms_config, $public_r;

        return $ecms_config['member']['defgroupid'] ? (int)$ecms_config['member']['defgroupid'] : (int)$public_r['defaultgroupid'];
    }

    /**
     * 验证登录验证符
     *
     * @return array
     */
    protected function qCheckLoginAuthstr(): array
    {
        global $ecms_config;

        $checkpass = getcvar('mlauth');

        if(!$checkpass) {

            return [
                'userid'    => '',
                'username'  => '',
                'groupid'   => '',
                'rnd'       => '',
                'rndt'      => '',
                'islogin'   => 0
            ];
        }

        $userid	    = (int)getcvar('mluserid');
        $username	= RepPostVar(getcvar('mlusername'));
        $rnd		= RepPostVar(getcvar('mlrnd'));
        $rndt       = RepPostVar(getcvar('mlrndt'));
        $groupid	= (int)getcvar('mlgroupid');
        $result     = [
            'userid'    => $userid,
            'username'  => $username,
            'groupid'   => $groupid,
            'rnd'       => $rnd,
            'rndt'      => $rndt
        ];

        if(!$userid || !$username || !$rnd) return $result;

        if(md5(md5($rnd . '--d-i!' . $userid . '-(g*od-' . $username . $ecms_config['cks']['ckrndtwo'] . '-' . $groupid) . '-#empire.cms!--p)h-o!me-' . $ecms_config['cks']['ckrndtwo']) !== $checkpass) return $result;

        return $result + ['islogin' => 1];
    }

    /**
     * 登录验证符
     *
     * @param int $userid
     * @param string $username
     * @param string $rnd
     * @param int $groupid
     * @param int $cookietime
     */
    protected function qGetLoginAuthstr(int $userid, string $username, string $rnd, int $groupid, int $cookietime = 0)
    {
        global $ecms_config;

        esetcookie('mlauth', md5(md5($rnd . '--d-i!' . $userid . '-(g*od-' . $username . $ecms_config['cks']['ckrndtwo'] . '-' . $groupid) . '-#empire.cms!--p)h-o!me-' . $ecms_config['cks']['ckrndtwo']), $cookietime);
    }

    /**
     * 清空验证码
     *
     * @param string $varname
     * @param int $ecms
     * @param int $isAdmin
     */
    protected function emptyShowKey(string $varname, int $ecms = 0, int $isAdmin = 0)
    {
        esetcookie($varname, '', 0, $ecms);
    }

    /**
     * 检查验证码
     *
     * @param string $varname
     * @param string $postval
     * @param int $dopr
     * @param int $ecms
     * @param int $isAdmin
     *
     * @throws Exception
     */
    protected function checkShowKey(string $varname, string $postval, int $dopr, int $ecms = 0, int $isAdmin = 0)
    {
        global $public_r;

        $pubkeytime	= 1 === $isAdmin ? $public_r['hkeytime'] : $public_r['keytime'];
        $pubkeyrnd	= 1 === $isAdmin ? $public_r['hkeyrnd'] : $public_r['keyrnd'];

        $r 		= explode(',', getcvar($varname, $ecms));
        $cktime	= isset($r[0]) && $r[0] ? (int)$r[0] : 0;
        $pass	= $r[1];
        $val	= $r[2];

        if($cktime > $this->nowtime || $this->nowtime - $cktime > $pubkeytime) throw new Exception('验证码已过期', 1200);

        if(empty(trim($postval))) throw new Exception('验证码验证失败', 1200);

        if(md5('d!i#g?o-d-' . md5(md5($varname . 'E.C#M!S^e-' . $postval) . '-E?m!P.i#R-e' . $cktime) . $pubkeyrnd . 'P#H!o,m^e-e') !== $pass){

            throw new Exception('验证码验证失败', 1200);
        }
    }

    /**
     * 转换权限
     *
     * @param int $groupid
     * @return array
     */
    protected function getLevel(int $groupid): array
    {
        global $level_r;

        if (!$groupid || !isset($level_r[$groupid]) || empty($level_r[$groupid])) return [];

        return array_filter($level_r[$groupid], fn($key) => in_array($key, ['level', 'groupname']), ARRAY_FILTER_USE_KEY);
    }

    /**
     * 去除无关数据
     *
     * @param array $data
     * @param bool $isSimple
     * @return array
     */
    protected function filter(array $data, bool $isSimple): array
    {
        return array_filter($data, fn($key) => in_array($key, $isSimple ? static::SIMPLE_FIELD : static::FULL_FIELD), ARRAY_FILTER_USE_KEY);
    }
}
